#include "GraphicsLibrary.h"

Point2_H operator + (const Point2_H &p0, const Point2_H &p1)
{
	return Point2_H(p0.X + p1.X, p0.Y + p1.Y);
}

Point2_H operator - (const Point2_H &p0, const Point2_H &p1)
{
	return Point2_H(p0.X - p1.X, p0.Y - p1.Y);
}

Point2_H operator * (const Point2_H &p, double scalar)
{
	return Point2_H(p.X * scalar, p.Y * scalar);
}

Point2_H operator * (double scalar, const Point2_H &p)
{
	return Point2_H(p.X * scalar, p.Y * scalar);
}

Point2_H operator / (const Point2_H &p, double scalar)
{
	if (ABS(scalar) < 1e-4)
	{
		scalar = 1.0;
	}

	return Point2_H(p.X / scalar, p.Y / scalar);
}

Point2_H operator += (Point2_H &p0, Point2_H &p1)
{
	p0.X += p1.X;
	p0.Y += p1.Y;
	return p0;
}

Point2_H operator -= (Point2_H &p0, Point2_H &p1)
{
	p0.X -= p1.X;
	p0.Y -= p1.Y;
	return p0;
}

Point2_H operator *= (Point2_H &p, double scalar)
{
	p.X *= scalar;
	p.Y *= scalar;
	return p;
}

Point2_H operator /= (Point2_H &p, double scalar)
{
	if (ABS(scalar) < 1e-4)
	{
		scalar = 1.0;
	}
	p.X /= scalar;
	p.Y /= scalar;
	return p;
}

bool operator == (Point2_H &p0, Point2_H &p1)
{
	return p0.X == p1.X && p0.Y == p1.Y;
}

Point3_H operator + (const Point3_H &p0, const Point3_H &p1)
{
	return Point3_H(p0.X + p1.X, p0.Y + p1.Y, p0.Z + p1.Z);
}

Point3_H operator - (const Point3_H &p0, const Point3_H &p1)
{
	return Point3_H(p0.X - p1.X, p0.Y - p1.Y, p0.Z - p1.Z);
}

Point3_H operator * (const Point3_H &p, double scalar)
{
	return Point3_H(p.X * scalar, p.Y * scalar, p.Z * scalar);
}

Point3_H operator * (double scalar, const Point3_H &p)
{
	return Point3_H(p.X * scalar, p.Y * scalar, p.Z * scalar);
}

Point3_H operator / (const Point3_H &p, double scalar)
{
	if (ABS(scalar) < 1e-4)
	{
		scalar = 1.0;
	}
	return Point3_H(p.X / scalar, p.Y / scalar, p.Z / scalar);
}

bool operator == (Point3_H &p0, Point3_H &p1)
{
	return p0.X == p1.X && p0.Y == p1.Y && p0.Z == p1.Z;
}

Vector3::Vector3(const Point3_H &p)
{
	X = p.X;
	Y = p.Y;
	Z = p.Z;
}

Vector3::Vector3(const Point3_H &p0, const Point3_H &p1)
{
	X = p1.X - p0.X;
	Y = p1.Y - p0.Y;
	Z = p1.Z - p0.Z;
}

double Vector3::Magnitude(void)
{
	return sqrt(X * X + Y * Y + Z * Z);
}

Vector3 Vector3::Normalize(void)
{
	Vector3 vector;
	double magnitude = sqrt(X * X + Y * Y + Z * Z);
	if (ABS(magnitude) < 1e-4)
	{
		magnitude = 1.0;
	}
	return Vector3(X / magnitude, Y / magnitude, Z / magnitude);
}

Vector3 operator + (const Vector3 &v0, const Vector3 &v1)
{
	return Vector3(v0.X + v1.X, v0.Y + v1.Y, v0.Z + v1.Z);
}

Vector3 operator - (const Vector3 &v0, const Vector3 &v1)
{
	return Vector3(v0.X - v1.X, v0.Y - v1.Y, v0.Z - v1.Z);
}

Vector3 operator * (const Vector3 &v, double scalar)
{
	return Vector3(v.X * scalar, v.Y * scalar, v.Z * scalar);
}

Vector3 operator * (double scalar, const Vector3 &v)
{
	return Vector3(v.X * scalar, v.Y * scalar, v.Z * scalar);
}

Vector3 operator / (const Vector3 &v, double scalar)
{
	if (ABS(scalar) < 1e-4)
	{
		scalar = 1.0;
	}
	return Vector3(v.X / scalar, v.Y / scalar, v.Z / scalar);
}

double DotProduct(const Vector3 &v0, const Vector3 &v1)
{
	return (v0.X * v1.X + v0.Y * v1.Y + v0.Z * v1.Z);
}

Vector3 CrossProduct(const Vector3 &v0, const Vector3 &v1)
{
	return Vector3(v0.Y * v1.Z - v0.Z * v1.Y, v0.Z * v1.X - v0.X * v1.Z, v0.X * v1.Y - v0.Y * v1.X);
}